﻿namespace System.Data.Entity
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;

    /// <summary>
    /// Entity Framework Extensions
    /// </summary>
    public static class EntityExtensions
    {

        #region "   Private Methods    "

        private static bool Save(DbContext context, Action<EntityExtensionException> errorAction)
        {
            try
            {

                return context.SaveChanges() > 0;

            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return false;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return false;
                    }
                    else
                        throw entityEx;
                }
            }
        }
        private static bool ChangeState(DbContext context, object entry, EntityState state, Action<EntityExtensionException> errorAction)
        {
            try
            {
                context.Entry(entry).State = state;
                return true;
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return false;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return false;
                    }
                    else
                        throw entityEx;
                }

            }
        }

        private static List<TResult> GetList<TEntity, TResult>(IQueryable<TResult> query, Action<EntityExtensionException> errorAction) where TEntity : class
        {
            try
            {
                Executing();
                return query.ToList();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return null;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return null;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        private static TResult GetFirst<TEntity, TResult>(IQueryable<TResult> query, Action<EntityExtensionException> errorAction)
            where TEntity : class
            where TResult : class
        {
            try
            {
                Executing();
                return query.FirstOrDefault();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return null;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return null;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        private static TResult GetSingle<TEntity, TResult>(IQueryable<TResult> query, Action<EntityExtensionException> errorAction)
            where TEntity : class
            where TResult : class
        {
            try
            {
                Executing();
                return query.SingleOrDefault();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return null;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return null;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        private static EntityExtensionException GetException(Exception ex)
        {
            var list = new List<string>();

            byte index = 1;
            //İlk Hata mesajı listeye ekleniyor.
            list.Add(string.Concat(index, " - ", ex.Message));

            //İnner exceptionları almak için bir değişken oluşturuyoruz.
            ex = ex.InnerException;

            //İnner exception null olana kadar yani iç hata mesajı bitene kadar dönüyoruz.
            while (ex != null)
            {
                index++;
                //inner exceptionda bulunan hada daha önce listeye eklenmemiş ise listeye ekliyoruz..
                if (!list.Where(p => p == ex.Message).Any())
                    list.Add(string.Concat(index, " - ", ex.Message));

                //ex değişkenini inner exceptionla değiştiriyoruz bu sayede inner exception null olana kadar tüm detayları alabileceğiz.
                ex = ex.InnerException;
            }
            string result = string.Empty;
            list.ForEach(f => result += string.Concat("\n", f));
            return new EntityExtensionException(result, ex);
        }

        private static void Executing()
        {
            if (EntityExtensionsAction.Executing != null)
            {
                EntityExtensionsAction.Executing();
            }
        }


        #endregion

        #region "   Single Add, Delete, Update Methods            "

        /// <summary>
        /// Veri Eklemek için kullanılan metod.
        /// </summary>
        /// <param name="db">DBContext</param>
        /// <param name="entry">Eklenecek Nesne</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static bool EntryAdd(this DbContext db, object entry, Action<EntityExtensionException> errorAction = null)
        {
            Executing();

            if (!ChangeState(db, entry, EntityState.Added, errorAction))
            {
                return false;
            }

            return Save(db, errorAction);
        }

        /// <summary>
        /// Veri Silmek için kullanılan metod.
        /// </summary>
        /// <param name="db">DBContext</param>
        /// <param name="entry">Silinecek Nesne</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static bool EntryDelete(this DbContext db, object entry, Action<EntityExtensionException> errorAction = null)
        {
            Executing();

            if (!ChangeState(db, entry, EntityState.Deleted, errorAction))
            {
                return false;
            }

            return Save(db, errorAction);
        }

        /// <summary>
        /// Veri Güncellemek için kullanılan metod.
        /// </summary>
        /// <param name="db">DBContext</param>
        /// <param name="entry">Güncellenecek Nesne</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static bool EntryUpdate(this DbContext db, object entry, Action<EntityExtensionException> errorAction = null)
        {
            Executing();

            if (!ChangeState(db, entry, EntityState.Modified, errorAction))
            {
                return false;
            }

            return Save(db, errorAction);
        }

        #endregion

        #region "   Multi Add, Delete, Update Methods             "

        /// <summary>
        /// Toplu Veri Eklemek için kullanılan metod.
        /// </summary>
        /// <param name="db">DBContext</param>
        /// <param name="entry">Eklenecek Nesne Dizisi</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>        
        public static bool EntryAddAll(this DbContext db, List<object> entryList, Action<EntityExtensionException> errorAction = null)
        {
            Executing();
            foreach (var entry in entryList)
            {
                if (!ChangeState(db, entry, EntityState.Added, errorAction))
                {
                    return false;
                }
            }
            return Save(db, errorAction);
        }

        /// <summary>
        /// Toplu Veri Silmek için kullanılan metod.
        /// </summary>
        /// <param name="db">DBContext</param>
        /// <param name="entry">Silinecek Nesne Dizisi</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static bool EntryDeleteAll(this DbContext db, object[] entryList, Action<EntityExtensionException> errorAction = null)
        {
            Executing();
            foreach (var entry in entryList)
            {
                if (!ChangeState(db, entry, EntityState.Deleted, errorAction))
                {
                    return false;
                }
            }
            return Save(db, errorAction);
        }

        /// <summary>
        /// Toplu Veri Güncellemek için kullanılan metod.
        /// </summary>
        /// <param name="db">DBContext</param>
        /// <param name="entry">Güncellenecek Nesne Dizisi</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static bool EntryUpdateAll(this DbContext db, object[] entryList, Action<EntityExtensionException> errorAction = null)
        {
            foreach (var entry in entryList)
            {
                if (!ChangeState(db, entry, EntityState.Modified, errorAction))
                {
                    return false;
                }
            }
            return Save(db, errorAction);
        }

        #endregion

        #region "   Select Methods   "

        /// <summary>
        /// Belirtilen tablodaki tüm verileri döndürür.
        /// </summary>
        /// <typeparam name="TEntity">Entry type</typeparam>
        /// <param name="db">DBContext</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static List<TEntity> Select<TEntity>(this DbContext db, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {

            return GetList<TEntity, TEntity>(db.Set<TEntity>(), errorAction);

        }

        /// <summary>
        /// Belirtilen tablodan belirtilen tüm verileri bir surrogate class içerisinde doldurup döndürür.
        /// Örnek Kullanımı: <code>var list = Db.Select&lt;SurrogateClass&gt;( s => new SurrogateClass{ Id = s.ProductID, Name = s.ProductName });</code>
        /// </summary>
        /// <typeparam name="TEntity"> Entry type </typeparam>
        /// <typeparam name="TResult"> Surrogate type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="selectExpression">Surrogate select expression</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        public static List<TResult> Select<TEntity, TResult>(this DbContext db, Expression<Func<TEntity, TResult>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
        {

            return GetList<TEntity, TResult>(db.Set<TEntity>().Select(selectExpression), errorAction);
        }


        /// <summary>
        /// Belirtilen tablodan belirtilen kayıtları anonymous type olarak dynamic türünde döndürür.
        /// Örnek Kullanımı: 
        /// <code>
        /// dynamic list = db.SelectDynamic&lt;Product>&gt;(s => new { Id = s.ProductID, Name = s.ProductName });
        /// foreach(var item in list)
        /// {
        ///     Console.WriteLine(string.Format("Product Id : {0} - Product Name : {1}",item.Id, item.Name));
        /// }
        /// </code>
        /// </summary>
        /// <typeparam name="TEntity">Entry type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="selectExpression">Select Expression</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static dynamic SelectDynamic<TEntity>(this DbContext db, Expression<Func<TEntity, dynamic>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
        {
            return GetList<TEntity, dynamic>(db.Set<TEntity>().Select(selectExpression), errorAction);
        }

        /// <summary>
        /// Belirtilen tablodan belirtilen kayıtları anonymous type olarak dynamic türünde döndürür.
        /// Örnek Kullanımı: 
        /// <code>
        /// dynamic list = db.SelectDynamic&lt;Product>&gt;(p=>p.ProductName.Containds("A"), s => new { Id = s.ProductID, Name = s.ProductName });
        /// foreach(var item in list)
        /// {
        ///     Console.WriteLine(string.Format("Product Id : {0} - Product Name : {1}",item.Id, item.Name));
        /// }
        /// </code>
        /// </summary>
        /// <typeparam name="TEntity">Entry type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="whereExpression">Where Expression</param>
        /// <param name="selectExpression">Select Expression</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static dynamic SelectDynamic<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, dynamic>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
        {
            return GetList<TEntity, dynamic>(db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);
        }
        #endregion

        #region Where Methods

        /// <summary>
        /// Belirtilen entry üzerinden where sorgusu çalıştırır ve geriye belirtilen entry listesi döner. Örnek Kullanım : 
        /// <code>
        /// var list = Db.Where&lt;Product&gt;(p => p.ProductName.Contains("Test"))
        /// </code>
        /// </summary>
        /// <typeparam name="T">Entry type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="whereExpression">Where Expression</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static List<T> Where<T>(this DbContext db, Expression<Func<T, bool>> whereExpression, Action<EntityExtensionException> errorAction = null) where T : class
        {
            return GetList<T, T>(db.Set<T>().Where(whereExpression), errorAction);
        }

        /// <summary>
        /// Belirtilen entry üzerinden where sorgusu çalıştırır ve geriye belirtilen TResult tipinden liste döner. Örnek Kullanım :
        /// <code>
        /// var list = Db.Where&lt;Product, SurrogateClass&gt;(s => new SurrogateClass {Id = s.ProductID, Name = s.ProductName});
        /// </code> 
        /// </summary>
        /// <typeparam name="TEntity">Entry type</typeparam>
        /// <typeparam name="TResult">Surrogate type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="whereExpression">Where expression</param>
        /// <param name="selectExpression">Select expression</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static List<TResult> Where<TEntity, TResult>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
        {
            return GetList<TEntity, TResult>(
                db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);
        }


        /// <summary>
        /// Belirtilen tablodan belirtilen kayıtları anonymous type olarak dynamic türünde döndürür.
        /// Örnek Kullanımı: 
        /// <code>
        /// dynamic list = db.Where&lt;Product>&gt;(s => new { Id = s.ProductID, Name = s.ProductName });
        /// foreach(var item in list)
        /// {
        ///     Console.WriteLine(string.Format("Product Id : {0} - Product Name : {1}",item.Id, item.Name));
        /// }
        /// </code>
        /// </summary>
        /// <typeparam name="TEntity">Entry type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="selectExpression">Select Expression</param>
        /// <param name="whereExpression">Where Expression</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static dynamic WhereDynamic<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, dynamic>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
        {
            return GetList<TEntity, dynamic>(db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);
        }


        #endregion

        #region First Methods

        public static TEntity First<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            return GetFirst<TEntity, TEntity>(db.Set<TEntity>()
                .Where(whereExpression), errorAction);
        }

        public static TResult First<TEntity, TResult>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
            where TResult : class
        {
            return GetFirst<TEntity, TResult>(db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);

        }

        public static dynamic FirstDynamic<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, dynamic>> selectExpression, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            return GetFirst<TEntity, dynamic>(db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);
        }

        #endregion

        #region Single Methods

        /// <summary>
        /// Tek kayıt getirmek için kullanılır.
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="db"></param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public static TEntity Single<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            return GetSingle<TEntity, TEntity>(db.Set<TEntity>().Where(whereExpression), errorAction);
        }

        public static TResult Single<TEntity, TResult>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> selectExpression, Action<EntityExtensionException> errorAction = null)
            where TEntity : class
            where TResult : class
        {
            return GetSingle<TEntity, TResult>(db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);

        }

        public static dynamic SingleDynamic<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, dynamic>> selectExpression, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            return GetSingle<TEntity, dynamic>(db.Set<TEntity>()
                .Where(whereExpression)
                .Select(selectExpression), errorAction);
        }

        #endregion

        #region Count and LongCount Methods


        public static int Count<TEntity>(this DbContext db, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            try
            {
                Executing();
                return db.Set<TEntity>().Count();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return -1;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return -1;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        public static int Count<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            try
            {
                Executing();
                return db.Set<TEntity>().Count(whereExpression);
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return -1;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return -1;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        public static long LongCount<TEntity>(this DbContext db, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            try
            {
                Executing();
                return db.Set<TEntity>().LongCount();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return -1;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return -1;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        public static long LongCount<TEntity>(this DbContext db, Expression<Func<TEntity, bool>> whereExpression, Action<EntityExtensionException> errorAction = null) where TEntity : class
        {
            try
            {
                Executing();
                return db.Set<TEntity>().LongCount(whereExpression);
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return -1;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return -1;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        #endregion

        #region Query Methods

        /// <summary>
        /// Belirtilen entry üzerinde belirtilen query çalıştırılıp belirtilen entry listesi olarak döndürür.
        /// Örnek Kullanım : <code>
        /// var query = db.Products.Where(p => p.ProductName.Contains("A")).OrderBy(p => p.ProductID).Skip(3).Take(5);
        /// var list = db.QueryToList&lt;Product&gt;(query, ErrorAction);
        /// </code>
        /// </summary>
        /// <typeparam name="TResult">Result type</typeparam>
        /// <param name="db">Db Context</param>
        /// <param name="query">Execute query</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static List<TResult> QueryToList<TResult>(this DbContext db, IQueryable<TResult> query, Action<EntityExtensionException> errorAction = null)
        {
            try
            {
                Executing();
                return query.ToList();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return null;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return null;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        /// <summary>
        /// Belirtilen query üzerinden First methodu çalıştırılarak TResult tipinde değer döndürür. 
        /// </summary>
        /// <typeparam name="TResult">Metoddan dönüş tipi</typeparam>
        /// <param name="db">Db context</param>
        /// <param name="query">Çalıştırılacak query</param>
        /// <param name="errorAction">Hata olursa yapılacak işlem. (Null bırakılırsa exception fırlatılır.)</param>
        /// <returns></returns>
        public static TResult QueryToFirst<TResult>(this DbContext db, IQueryable<TResult> query, Action<EntityExtensionException> errorAction = null) where TResult : class
        {
            try
            {
                Executing();
                return query.FirstOrDefault();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return null;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return null;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        /// <summary>
        /// Sql sorgusu belirtilen kayıtları çeker.
        /// </summary>
        /// <typeparam name="TResult">Geri dönüş tipi</typeparam>
        /// <param name="db">DBContext</param>
        /// <param name="sql">tsql kodunuz</param>
        /// <param name="parameters">tsql parametreleri.</param>
        /// <param name="errorAction">Hata yakalama</param>
        /// <returns></returns>
        public static List<TResult> SqlQuery<TResult>(this DbContext db, string sql, object[] parameters, Action<EntityExtensionException> errorAction = null) where TResult : class
        {
            try
            {
                Executing();
                return db.Database.SqlQuery<TResult>(sql, parameters).ToList();
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return null;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return null;
                    }
                    else
                        throw entityEx;
                }
            }
        }

        #endregion

        /// <summary>
        /// Stored Procedure çalıştırmak için kullanılır. Örnek : Db.ExecuteSP(() => { Db.AddProductToStoredProcedure("Computer"); });
        /// </summary>
        /// <param name="db">Db Context</param>
        /// <param name="spMethod">SpMethod</param>
        /// <param name="errorAction"></param>
        public static bool ExecuteSP(this DbContext db, Action spMethod, Action<EntityExtensionException> errorAction = null)
        {
            try
            {
                spMethod();
                return true;
            }
            catch (Exception ex)
            {
                var entityEx = GetException(ex);
                if (errorAction != null)
                {
                    errorAction(entityEx);
                    return false;
                }
                else
                {
                    if (EntityExtensionsAction.DbError != null)
                    {
                        EntityExtensionsAction.DbError(entityEx);
                        return false;
                    }
                    else
                        throw entityEx;
                }
            }
        }

    }
}